﻿<%@ WebHandler Language="C#" Class="ContainerCheckVue3PageHandler" %>

/* Description:新框架检验后端接口
 * Copyright (c) : 通力凯顿（北京）系统集成有限公司
 * Writer:zhunan 
 * create Date:2024.4.11
 */

using System;
using System.IO;
using System.Web;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
using System.Collections.Generic;
using System.Data;
using System.Text;
using BusinessRule.DTO;
using DatabaseAccess.DBUtility;
using BusinessRule.Business;
using BusinessRule.IBusiness;
using BusinessRule.BusinessFactory;
using System.Net;
using System.Configuration;
using StackExchange.Redis;
using BusinessRule.Common;
using System.Linq;
using System.Web.SessionState;

public class ContainerCheckVue3PageHandler : IHttpHandler, IRequiresSessionState
{
    uLMSCommonIBusiness m_Common = uMESBusinessFactory.instance.GetuLMSCommonObject();
    uLMSCheckIBusiness m_CheckObj = uMESBusinessFactory.instance.GetuLMSCheckObject();
    uLMSWorkReportIBusiness m_WorkReportObj = uMESBusinessFactory.instance.GetuLMSWorkReportObject();
    uLMSContainerIBusiness m_ContainerObj = uMESBusinessFactory.instance.GetuLMSContainerObject();
    uLMSContainercurrentinfoIBusiness m_ConCurrentinfo = uMESBusinessFactory.instance.GetuLMSContainerCurrentInfoObject();
    uLMSUserLoginIBusiness m_UserLoginObject = uMESBusinessFactory.instance.GetuLMSUserLoginObject();
    CurrentUserInfo userInfo = new CurrentUserInfo();
    public bool IsReusable { get { return false; } }
    public void ProcessRequest(HttpContext context)
    {
        string requestjson = "";

        using (System.IO.StreamReader reader = new StreamReader(context.Request.InputStream)) { requestjson = reader.ReadToEnd(); }
        JObject jObject = JsonConvert.DeserializeObject(requestjson) as JObject;
        if (jObject["type"] != null)
        {
            try
            {
                uMESProcessResult r = new uMESProcessResult();
                context.Response.ContentType = "text/json";
                string type = jObject["type"].ToString();
                switch (type)
                {
                    case "getUnCheckContainerData":
                        r = getUnCheckContainerData(jObject);//查询待检验批次数据
                        context.Response.Write(JsonConvert.SerializeObject(r));
                        break;
                    case "getUnCheckContainerDetail":
                        r = getUnCheckContainerDetail(jObject);//查询待检验批次--表格明细
                        context.Response.Write(JsonConvert.SerializeObject(r));
                        break;
                    case "getDispatchAndReportInfo":
                        r = getDispatchAndReportInfo(jObject);//查询派工及报工信息
                        context.Response.Write(JsonConvert.SerializeObject(r));
                        break;
                    case "checkContainerIsHold":
                        r = checkContainerIsHold(jObject);//校验批次是否暂停
                        context.Response.Write(JsonConvert.SerializeObject(r));
                        break;
                    case "isHavingReworkOrDelegate":
                        r = isHavingReworkOrDelegate(jObject);//校验是否有委托计量或返工返修
                        context.Response.Write(JsonConvert.SerializeObject(r));
                        break;
                    case "isHavingNonconforming":
                        r = isHavingNonconforming(jObject);//校验是否有未审理的不合格品审理记录
                        context.Response.Write(JsonConvert.SerializeObject(r));
                        break;
                    case "getFirstCheckContainerNo":
                        r = getFirstCheckContainerNo(jObject);//获取首件批次号
                        context.Response.Write(JsonConvert.SerializeObject(r));
                        break;
                    case "getFirstCheckBillNo":
                        r = getFirstCheckBillNo(jObject);//获取首件检验单号
                        context.Response.Write(JsonConvert.SerializeObject(r));
                        break;
                    case "getWorkerInfo":
                        r = getWorkerInfo(jObject);//获取报工信息
                        context.Response.Write(JsonConvert.SerializeObject(r));
                        break;
                    case "SaveCheckInfo":
                        r = SaveCheckInfo(jObject);//保存检验
                        context.Response.Write(JsonConvert.SerializeObject(r));
                        break;
                    case "SaveCheckPointSession"://保存session
                        r = SaveCheckPointSession(context, jObject);
                        context.Response.Write(JsonConvert.SerializeObject(r));
                        break;
                    case "GetSurpassBill"://查询超越单信息
                        r = GetSurpassBill(jObject);
                        context.Response.Write(JsonConvert.SerializeObject(r));
                        break;
                    case "isInputCheckPointResult":
                        r = isInputCheckPointResult(jObject);//查询是否有未处理的检测项
                        context.Response.Write(JsonConvert.SerializeObject(r));
                        break;
                    case "saveCheckEntrust":
                        r = saveCheckEntrust(jObject);//保存理化或计量标识
                        context.Response.Write(JsonConvert.SerializeObject(r));
                        break;
                    case "isInvalidSpecialCheck":
                        r = isInvalidSpecialCheck(jObject);//验证批次工序是否无效（特殊验证） add by zhangrj 20250409
                        context.Response.Write(JsonConvert.SerializeObject(r));
                        break;
                    default:
                        break;
                }
            }
            catch (Exception e)
            {
                uMESProcessResult r = new uMESProcessResult() { ReturnData = null, RowCount = "0", Code = "500", Message = e.Message };
                context.Response.ContentType = "text/json";
                context.Response.Write(JsonConvert.SerializeObject(r));
            }
        }
    }

    uMESProcessResult getUnCheckContainerData(JObject obj)
    {
        string sql = @"
SELECT NVL(c.workflowroute,c.productname) productname,c.productid,c.workflowstepname,c.workflowstepid,c.specno, c.workflowid,c.workflowstepsequence AS SEQUENCE,c.togetherflag,
       c.containertype,DECODE(c.containertype,2,'批量加工',3,'批量带子序号', 7,'单件加工') AS containertypename,c.mfgordername,c.planqty,c.plannedstartdate,
       c.plannedcompletiondate,c.workcentername,c.workcenterid,c.factoryid,c.productdescription,c.productrevision,NVL(ua.attributevalue,c.productdescription) zbjh,
       (NVL(c.workflowroute,c.productname)||'/'||c.containerno) productbatch,
       (c.productname||'/'||c.containerno) productbatchhidden,c.containerno,
       SUM(c.qty) AS wipqty,--在制数
       '' containerid,''containername,NULL workreportnum,'' facontianerid,
       NULL firstchecknum,NULL stepchecknum,'' iskey,'' specname,'' specrevision,''parentspecno,
       NULL nonconformingnum,NULL originalfactoryid,MIN(csw.createdate) reportdate,ROUND(SYSDATE - MIN(csw.createdate),2) checkwaitdays
FROM containercurrentinfo c 
LEFT JOIN userattribute ua ON ua.parentid = c.mfgorderid AND ua.userattributename = '组别件号'
LEFT JOIN containerstepnoship csn ON csn.containerid=c.containerid AND csn.workflowstepid=c.workflowstepid AND csn.isuse=0 AND csn.noship=1
LEFT JOIN containerstepworkreport csw ON csw.containerid = c.containerid AND csw.workflowstepid = c.workflowstepid AND csw.isuse = 0";

        //报工选择检验员
        if (obj["checkerid"] != null && obj["checkerid"].ToString() != "")
        {
            string checkerSql = @"
--报工选择检验员
INNER JOIN(
      SELECT csw.containerid, csw.workflowstepid
      FROM containerstepworkreport csw
      WHERE (csw.checkerid = '{0}' OR csw.checkerid IS NULL) AND csw.isuse = 0
      GROUP BY csw.containerid, csw.workflowstepid
) cki ON cki.containerid=c.containerid AND cki.workflowstepid = c.workflowstepid";
            checkerSql = string.Format(checkerSql, obj["checkerid"].ToString());
            sql += checkerSql;
        }

        sql += @"
WHERE c.factoryid='{0}' AND (c.firstchecknum=1 OR c.stepchecknum=1) AND c.splitnum=0 AND c.containerstatus=1  
      AND (CASE WHEN c.originalfactoryid='{0}' AND csn.containerstepnoshipid IS NULL THEN c.specfactoryid ELSE '{0}' END)='{0}' 
      AND (CASE WHEN c.originalfactoryid<>'{0}' AND csn.containerstepnoshipid IS NULL THEN c.shipnum ELSE 5 END)>4
      AND c.containertype='7'";

        if (obj["containername"] != null && obj["containername"].ToString() != "")
        {
            sql += string.Format("  AND c.containername LIKE '%{0}%'", obj["containername"].ToString());
        }

        if (obj["productname"] != null && obj["productname"].ToString() != "")
        {
            sql += string.Format("  AND c.productname LIKE '%{0}%'", obj["productname"].ToString());
        }

        if (obj["mfgordername"] != null && obj["mfgordername"].ToString() != "")
        {
            sql += string.Format("  AND c.mfgordername LIKE '%{0}%'", obj["mfgordername"].ToString());
        }

        if (obj["specno"] != null && obj["specno"].ToString() != "")
        {
            sql += string.Format("  AND c.specno LIKE '%{0}%'", obj["specno"].ToString());
        }

        sql += @"
GROUP BY c.productid, c.productname, c.workflowstepname,c.workflowstepid, c.workflowid, c.workflowstepsequence, c.specno,
         c.togetherflag, c.containertype,c.mfgordername,c.planqty, c.plannedstartdate, c.plannedcompletiondate,c.workflowroute,
         c.workcentername,c.workcenterid,c.factoryid,c.productdescription,c.productrevision,ua.attributevalue,c.containerno

UNION ALL

SELECT NVL(c.workflowroute,c.productname) productname,c.productid,c.workflowstepname,c.workflowstepid,c.specno, c.workflowid,c.workflowstepsequence AS SEQUENCE,c.togetherflag,
       c.containertype,DECODE(c.containertype,2,'批量加工',3,'批量带子序号', 7,'单件加工') AS containertypename,c.mfgordername,c.planqty,c.plannedstartdate,
       c.plannedcompletiondate,c.workcentername,c.workcenterid,c.factoryid,c.productdescription,c.productrevision,NVL(ua.attributevalue,c.productdescription) zbjh,
       (NVL(c.workflowroute,c.productname)||'/'||c.containerno) productbatch,
       (c.productname||'/'||c.containerno) productbatchhidden,c.containerno,
       c.qty AS wipqty, 
       c.containerid,c.containername,c.workreportnum,c.containerid AS facontianerid,
       c.firstchecknum,c.stepchecknum,c.iskey,c.specname,c.specrevision,c.parentspecno,
       c.nonconformingnum,c.originalfactoryid,MIN(csw.createdate) reportdate,ROUND(SYSDATE - MIN(csw.createdate),2) checkwaitdays
FROM containercurrentinfo c 
LEFT JOIN userattribute ua ON ua.parentid = c.mfgorderid AND ua.userattributename = '组别件号'
LEFT JOIN containerstepnoship csn ON csn.containerid=c.containerid AND csn.workflowstepid=c.workflowstepid AND csn.isuse=0 AND csn.noship=1
LEFT JOIN containerstepworkreport csw ON csw.containerid = c.containerid AND csw.workflowstepid = c.workflowstepid AND csw.isuse = 0";

        //报工选择检验员
        if (obj["checkerid"] != null && obj["checkerid"].ToString() != "")
        {
            string checkerSql = @"
--报工选择检验员
INNER JOIN(
      SELECT csw.containerid, csw.workflowstepid
      FROM containerstepworkreport csw
      WHERE (csw.checkerid = '{0}' OR csw.checkerid IS NULL) AND csw.isuse = 0
      GROUP BY csw.containerid, csw.workflowstepid
) cki ON cki.containerid=c.containerid AND cki.workflowstepid = c.workflowstepid";
            checkerSql = string.Format(checkerSql, obj["checkerid"].ToString());
            sql += checkerSql;
        }

        sql += @"
WHERE c.factoryid='{0}'  AND (c.firstchecknum=1 OR c.stepchecknum=1) AND c.splitnum=0 AND c.containerstatus=1  
      AND (CASE WHEN c.originalfactoryid='{0}' AND csn.containerstepnoshipid IS NULL THEN c.specfactoryid ELSE '{0}' END)='{0}' 
      AND (CASE WHEN c.originalfactoryid<>'{0}' AND csn.containerstepnoshipid IS NULL THEN c.shipnum ELSE 5 END)>4
      AND c.containertype<>'7'";

        if (obj["containername"] != null && obj["containername"].ToString() != "")
        {
            sql += string.Format("  AND c.containername = '{0}'", obj["containername"].ToString());
        }

        if (obj["productname"] != null && obj["productname"].ToString() != "")
        {
            sql += string.Format("  AND c.productname LIKE '%{0}%'", obj["productname"].ToString());
        }

        if (obj["mfgordername"] != null && obj["mfgordername"].ToString() != "")
        {
            sql += string.Format("  AND c.mfgordername LIKE '%{0}%'", obj["mfgordername"].ToString());
        }

        if (obj["specno"] != null && obj["specno"].ToString() != "")
        {
            sql += string.Format("  AND c.specno LIKE '%{0}%'", obj["specno"].ToString());
        }

        sql += @"
GROUP BY c.workflowroute,c.productname,c.productid,c.workflowstepname,c.workflowstepid,c.specno,c.workflowid,c.workflowstepsequence,c.togetherflag,
         c.containertype,c.mfgordername,c.planqty,c.plannedstartdate,
         c.plannedcompletiondate,c.workcentername,c.workcenterid,c.factoryid,c.productdescription,c.productrevision,ua.attributevalue,c.containerno,
         c.qty,c.containerid,c.containername,c.workreportnum,c.firstchecknum,c.stepchecknum,c.iskey,c.specname,c.specrevision,c.parentspecno,
         c.nonconformingnum,c.originalfactoryid";

        sql = string.Format(sql, obj["factoryid"].ToString());

        DataTable dtResult = DatabaseHelper.Query_ReturnDatTable(sql);

        foreach (DataColumn col in dtResult.Columns)
        {
            col.ColumnName = col.ColumnName.ToLower();
        }
        return new uMESProcessResult() { ReturnData = dtResult, RowCount = dtResult.Rows.Count.ToString(), Code = "200", Message = "请求成功" };
    }

    uMESProcessResult getUnCheckContainerDetail(JObject obj)
    {
        string sql = @"
SELECT DECODE(ccs.notes,NULL,'否','是') ishandle,f.factoryname originalfactoryname,c.* 
FROM containercurrentinfo c
LEFT JOIN factory f ON f.factoryid = c.originalfactoryid
LEFT JOIN containerchecksuspending ccs ON ccs.containerid=c.containerid AND ccs.workflowstepid=c.workflowstepid AND ccs.isuse=0  
LEFT JOIN containerstepnoship csn ON csn.containerid=c.containerid AND csn.workflowstepid=c.workflowstepid AND csn.isuse=0 AND csn.noship=1";

        //报工选择检验员
        if (obj["checkerid"] != null && obj["checkerid"].ToString() != "")
        {
            string checkerSql = @"
--报工选择检验员
INNER JOIN(
      SELECT csw.containerid, csw.workflowstepid
      FROM containerstepworkreport csw
      WHERE (csw.checkerid = '{0}' OR csw.checkerid IS NULL) AND csw.isuse = 0
      GROUP BY csw.containerid, csw.workflowstepid
) cki ON cki.containerid=c.containerid AND cki.workflowstepid = c.workflowstepid";
            checkerSql = string.Format(checkerSql, obj["checkerid"].ToString());
            sql += checkerSql;
        }

        sql += @"
WHERE c.factoryid='{0}'  AND (c.firstchecknum=1 OR c.stepchecknum=1) 
      AND c.splitnum=0 AND c.containerstatus=1  
      AND (CASE WHEN c.originalfactoryid='{0}' AND csn.containerstepnoshipid IS NULL THEN c.specfactoryid ELSE '{0}' END) = '{0}' 
      AND (CASE WHEN c.originalfactoryid<>'{0}' AND csn.containerstepnoshipid IS NULL THEN c.shipnum ELSE 5 END)>4";

        if (obj["containertype"].ToString() != "7")
        {
            sql += string.Format(" AND c.containertype<>7 AND c.togetherflag='{0}'", obj["togetherflag"].ToString());
        }
        else
        {
            string conditionSql = @" AND c.containertype=7 AND c.togetherflag='{0}' AND c.productid='{1}' AND c.workflowstepid='{2}' AND c.mfgordername='{3}'";
            sql += string.Format(conditionSql,
                obj["togetherflag"].ToString(),
                obj["productid"].ToString(),
                obj["workflowstepid"].ToString(),
                obj["mfgordername"].ToString());
        }

        sql += @" ORDER BY c.containername ";

        sql = string.Format(sql, obj["factoryid"].ToString());

        DataTable dtResult = DatabaseHelper.Query_ReturnDatTable(sql);
        if (dtResult.Rows.Count == 0)
        {
            return new uMESProcessResult() { ReturnData = dtResult, RowCount = dtResult.Rows.Count.ToString(), Code = "200", Message = "请求成功" };
        }

        DataTable dtSurpass = getContainerSurpassInfo(dtResult, obj);
        dtResult.Columns.Add("ishavesurpass");//是否有超越单
        foreach (DataRow dr in dtResult.Rows)
        {
            string filter = string.Format("containerid = '{0}'", dr["containerid"].ToString());
            if (dtSurpass.Select(filter).Length > 0)
            {
                dr["ishavesurpass"] = "是";
            }
            else
            {
                dr["ishavesurpass"] = "否";
            }
        }

        foreach (DataColumn col in dtResult.Columns)
        {
            col.ColumnName = col.ColumnName.ToLower();
        }
        return new uMESProcessResult() { ReturnData = dtResult, RowCount = dtResult.Rows.Count.ToString(), Code = "200", Message = "请求成功" };
    }

    //查询批次超越单信息
    DataTable getContainerSurpassInfo(DataTable dtResult, JObject obj)
    {
        string containerIDs = "", ProcessNo = "", SpecNo = "";
        foreach (DataRow dr in dtResult.Rows)
        {
            containerIDs += string.Format("'{0}',", dr["containerid"].ToString());
        }

        if (containerIDs != "")
        {
            containerIDs = containerIDs.TrimEnd(',');
        }

        DataTable workFlowDt = m_Common.GetWorkFlowNameByWorkFLowID(obj["workflowid"].ToString());
        if (workFlowDt.Rows.Count > 0)
        {
            ProcessNo = workFlowDt.Rows[0]["process_No"].ToString();
        }

        DataTable dtSpec = m_Common.GetSpecNameByWorkflowStepID(obj["workflowstepid"].ToString());
        if (dtSpec.Rows.Count > 0)
        {
            SpecNo = dtSpec.Rows[0]["specno"].ToString();
        }

        //查询批次超越单信息
        string surPassSql = @"
SELECT DISTINCT sbm.containerid,(sbi.productname||'/'||sbi.containername) containername,sbi.processno workflowname,sbm.specno,sbd.remark,sbi.* 
FROM surpassbillinfo sbi 
LEFT JOIN surpassbilldetail sbd ON sbd.surpassbillinfoid=SBI.surpassbillinfoid--明细
LEFT JOIN surpassbillmapping sbm  ON sbm.surpassbilldetailid=sbd.surpassbilldetailid--映射
WHERE sbm.containerid IN ({0}) AND sbi.processno = '{1}' AND sbm.specno = '{2}'";
        surPassSql = string.Format(surPassSql, containerIDs, ProcessNo, SpecNo);

        return DatabaseHelper.Query_ReturnDatTable(surPassSql);
    }

    //查询批次派工、报工信息
    uMESProcessResult getDispatchAndReportInfo(JObject obj)
    {
        string sql = @"
SELECT csd.containerid,csd.containername,csw.checktype,
       csd.dispatchemployeename,csd.dispatchdate,csd.reportemployeename,csd.reportdate,csd.reportqty,
       dt.recvdate receivedate,e.fullname receiveemp,csd.dispatchid,csd.containersteprecordid
FROM containersteprecord csd
LEFT JOIN containercurrentinfo cci ON cci.containerid = csd.containerid
LEFT JOIN containerstepworkreport csw ON csw.containerstepworkreportid = csd.containersteprecordid AND csw.isuse = 0
LEFT JOIN containerstepdispatch dt ON dt.containerstepdispatchid = csd.dispatchid AND dt.isuse = 0
LEFT JOIN employee e ON e.employeeid = dt.recvemployeeid
WHERE cci.togetherflag = '{0}' AND csd.workflowstepid = '{1}' AND csd.checkdate IS NULL
ORDER BY csd.reportdate";

        sql = string.Format(sql, obj["togetherflag"].ToString(), obj["workflowstepid"].ToString());

        DataTable dtResult = DatabaseHelper.Query_ReturnDatTable(sql);

        foreach (DataColumn col in dtResult.Columns)
        {
            col.ColumnName = col.ColumnName.ToLower();
        }

        return new uMESProcessResult() { ReturnData = dtResult, RowCount = dtResult.Rows.Count.ToString(), Code = "200", Message = "请求成功" };
    }

    /// <summary>
    /// 校验批次工序是否无效（特殊验证） add by zhangrj 20250409
    /// 验证特殊过程、三定卡片（后续可以直接在此处新增其他验证）
    /// </summary>
    /// <param name="obj"></param>
    /// <returns></returns>
    uMESProcessResult isInvalidSpecialCheck(JObject obj)
    {
        /*1、验证检验工序是否是有效的特殊过程工序 add by 20250409*/
        DataTable dt = JsonConvert.DeserializeObject<DataTable>(obj["postData"].ToString());
        string msg = string.Empty;
        DataTable dtEmp = m_Common.GetEmployeeByEmployeeID(obj["checkerid"].ToString());//获取检验人信息
        CurrentUserInfo userInfo = new CurrentUserInfo()
        {
            EmployeeID = obj["checkerid"].ToString(),
            EmployeeName = dtEmp.Rows[0]["EmployeeName"].ToString(),
            FactoryID = dtEmp.Rows[0]["orgfactoryid"].ToString(),
            FullName = dtEmp.Rows[0]["FullName"].ToString()
        };
        SpecialReportValidDTO srvDto = m_CheckObj.ValidSpecialCourseSpecReportByCheck(dt, userInfo);
        if (!srvDto.IsValid)//验证是否无效的特殊过程
        {
            return new uMESProcessResult() { ReturnData = true, RowCount = "0", Code = "500", Message = msg };
        }
        /*2、验证检验工序是否是有效的三定卡片工序 add by 20251011*/
        Tuple<bool, string> resTu = m_CheckObj.ValidSpecThreeFixedCardByCheck(dt, userInfo);
        if (!resTu.Item1)
        {
            return new uMESProcessResult() { ReturnData = true, RowCount = "0", Code = "500", Message = resTu.Item2 };
        }
        /*验证通过*/
        return new uMESProcessResult() { ReturnData = false, RowCount = "0", Code = "200", Message = srvDto.IsUnder95Day ? "验证通过，" + srvDto.Message : "验证通过" };
    }

    //校验批次是否暂停
    uMESProcessResult checkContainerIsHold(JObject obj)
    {
        DataTable dt = JsonConvert.DeserializeObject<DataTable>(obj["postData"].ToString());
        string msg = "请求成功";
        foreach (DataRow dr in dt.Rows)
        {
            if (m_Common.JudeContainerHold(dr["containerid"].ToString(), ref msg))
            {
                msg = "批次:【" + dr["containername"] + "】已暂停，暂停原因：" + msg;
                return new uMESProcessResult() { ReturnData = true, RowCount = "0", Code = "200", Message = msg };
            }
        }
        return new uMESProcessResult() { ReturnData = false, RowCount = "0", Code = "200", Message = msg };
    }

    //校验是否有委托计量或返工返修
    uMESProcessResult isHavingReworkOrDelegate(JObject obj)
    {
        DataTable dt = JsonConvert.DeserializeObject<DataTable>(obj["postData"].ToString());
        string msg = "";
        foreach (DataRow dr in dt.Rows)
        {
            int num = m_CheckObj.IshavingReworkORDelegate(dr);
            if (num == 1)
            {
                msg = "批次:【" + dr["containername"] + "】有委托计量记录";
                return new uMESProcessResult() { ReturnData = true, RowCount = "0", Code = "200", Message = msg };
            }
            else if (num == 2)
            {
                msg = "批次:【" + dr["containername"] + "】有返工返修记录";
                return new uMESProcessResult() { ReturnData = true, RowCount = "0", Code = "200", Message = msg };
            }
        }
        return new uMESProcessResult() { ReturnData = false, RowCount = "0", Code = "200", Message = "请求成功" };
    }

    //校验是否有未审理的不合格品审理记录
    uMESProcessResult isHavingNonconforming(JObject obj)
    {
        DataTable dt = JsonConvert.DeserializeObject<DataTable>(obj["postData"].ToString());
        string containerIDs = "";
        foreach (DataRow dr in dt.Rows)
        {
            containerIDs += string.Format("'{0}',", dr["containerid"].ToString());
        }

        if (containerIDs != "")
        {
            containerIDs = containerIDs.TrimEnd(',');
        }

        Dictionary<string, string> nonPara = new Dictionary<string, string>();
        nonPara["ContainerIDs"] = containerIDs;
        nonPara["WorkFlowStepID"] = dt.Rows[0]["workflowstepid"].ToString();

        DataTable dtNonConformingData = m_CheckObj.GetContainerNonconformingInfo(nonPara);
        foreach (DataRow nonRow in dtNonConformingData.Rows)
        {
            //如果存在未审理记录
            if (Convert.IsDBNull(nonRow["CheckEmployeeID"]) && Convert.ToInt64(nonRow["ZBHGPS"]) > 0)
            {
                string msg = "批次:【" + nonRow["containername"] + "】存在未审理的不合格品审理记录";
                return new uMESProcessResult() { ReturnData = true, RowCount = "0", Code = "200", Message = msg };
            }
        }
        return new uMESProcessResult() { ReturnData = false, RowCount = "0", Code = "200", Message = "请求成功" };
    }

    //获取首件批次号
    uMESProcessResult getFirstCheckContainerNo(JObject obj)
    {
        string firstCheckContainerNo = m_CheckObj.GetFirstCheckContainerNo(obj["containerid"].ToString(), obj["workflowstepid"].ToString());
        return new uMESProcessResult() { ReturnData = firstCheckContainerNo, RowCount = "0", Code = "200", Message = "请求成功" };
    }

    //获取首件检验单号
    uMESProcessResult getFirstCheckBillNo(JObject obj)
    {
        string firstCheckBillNo = m_CheckObj.GetFirstCheckBillNo(obj["factorycode"].ToString());
        return new uMESProcessResult() { ReturnData = firstCheckBillNo, RowCount = "0", Code = "200", Message = "请求成功" };
    }

    //获取报工人数据
    uMESProcessResult getWorkerInfo(JObject obj)
    {
        DataTable dt = JsonConvert.DeserializeObject<DataTable>(obj["postData"].ToString());
        string strContainer = "";
        foreach (DataRow dr in dt.Rows)
        {
            strContainer += String.Format("'{0}',", dr["ContainerID"].ToString());
        }

        if (!string.IsNullOrWhiteSpace(strContainer))
        {
            strContainer = strContainer.Substring(0, strContainer.Length - 1);
        }

        Dictionary<string, string> para = new Dictionary<string, string>();
        para.Add("ContainerID", strContainer);
        para.Add("WorkflowStepID", dt.Rows[0]["WorkflowStepID"].ToString());
        //首检
        if (dt.Rows[0]["firstchecknum"].ToString() == "1")
        {
            para.Add("CheckType", "1");
        }
        else
        {
            para.Add("CheckType", "2");
        }

        //分厂存在【报工选择检验】配置项
        if (obj["workerSelectChecker"] != null && obj["workerSelectChecker"].ToString() == "是")
        {
            para.Add("CheckerID", obj["checkerid"].ToString());//按检验员筛选报工记录
        }

        DataTable workerDT = m_WorkReportObj.GetWorkerInfo(para);

        foreach (DataColumn col in workerDT.Columns)
        {
            col.ColumnName = col.ColumnName.ToLower();
        }
        return new uMESProcessResult() { ReturnData = workerDT, RowCount = workerDT.Rows.Count.ToString(), Code = "200", Message = "请求成功" };
    }

    //校验检验信息
    bool ValidateStepCheckInfo(JObject obj, ref List<ContainerCheckInfoDTO> checkData, DataTable Lossdt, DataRow row, ref string strInfo)
    {
        //再给报废表增加以下几列
        Lossdt.Columns.Add("CheckerID");
        foreach (DataRow dr in Lossdt.Rows)
        {
            //add:Wangjh 20190325 有试件数就是试件报工类型
            if (dr["specimenqty"] != null && dr["specimenqty"].ToString() != "0")
            {
                dr["checktype"] = "3";
            }
            //检验员默认是当前登录人
            dr["CheckerID"] = userInfo.EmployeeID;
        }

        string strType = row["containertype"].ToString();//获取批次类型
        if (strType == "3")
        {
            // 报工记录表，存报工记录对应的报废数，检验数和合格数等 add by tianFW 2018 年 11 月 2 日
            DataTable workreportdt = Lossdt.DefaultView.ToTable(true, new string[] { "containerstepworkreportid", "checktype", "qty" });
            int LossQty = 0;
            int CheckQty = 0;
            foreach (DataRow wpdr in workreportdt.Rows)
            {
                ContainerCheckInfoDTO dtoCheckInfo = new ContainerCheckInfoDTO();
                LossQty = 0;
                CheckQty = Convert.ToInt32(wpdr["Qty"]); // 获取报工总数
                foreach (DataRow ldr in Lossdt.Rows)
                {
                    if (ldr["ContainerStepWorkReportID"].ToString() == wpdr["ContainerStepWorkReportID"].ToString())
                    {
                        //lossQty -> editLossQty
                        if (!string.IsNullOrWhiteSpace(Convert.ToString(ldr["editLossQty"])))
                        {
                            LossQty += Convert.ToInt32(ldr["editLossQty"]);
                        }
                        dtoCheckInfo.DefectQty += Convert.ToInt32(ldr["editDefectqty"]);
                        dtoCheckInfo.ReworkQty += Convert.ToInt32(ldr["editReworkQty"]);
                        //add by longb 2023-12-21 不合格特征 IDS
                        dtoCheckInfo.UnqualifiedFeatureIds = Convert.IsDBNull(ldr["unqualifiedfeatureids"]) ? "" : ldr["unqualifiedfeatureids"].ToString();
                    }
                }

                dtoCheckInfo.ContainerName = row["ContainerName"].ToString();
                dtoCheckInfo.ContainerID = row["ContainerID"].ToString();
                dtoCheckInfo.WorkflowstepID = row["WorkflowStepID"].ToString();
                dtoCheckInfo.WIPQty = Convert.ToInt32(row["WipQty"].ToString());
                dtoCheckInfo.CheckQty = CheckQty;
                dtoCheckInfo.FactoryID = userInfo.FactoryID;
                dtoCheckInfo.CheckerID = userInfo.EmployeeID;
                dtoCheckInfo.CheckNote = obj["checkNote"].ToString();//检验备注
                dtoCheckInfo.FirstCheckContainerNo = obj["firstCheckContainerNo"].ToString();//首检批次号
                dtoCheckInfo.FirstCheckBillNo = obj["firstCheckBillNo"].ToString();//首件检验单号
                //if (row["CheckTypeNote"].ToString() == "2")
                //{
                //    dtoCheckInfo.CheckTypeNote = 2; // 装配检 add:Wangjh 2017-9-18
                //}
                dtoCheckInfo.ReportType = Convert.ToInt32(wpdr["CheckType"].ToString()); // 报工类型
                dtoCheckInfo.ContainerStepWorkReportID = wpdr["ContainerStepWorkReportID"].ToString();
                dtoCheckInfo.AcceptanceQty = CheckQty - LossQty;
                dtoCheckInfo.LossQty = LossQty;
                dtoCheckInfo.AcceptanceQty2 = dtoCheckInfo.AcceptanceQty - dtoCheckInfo.DefectQty - dtoCheckInfo.ReworkQty; //add:Wangjh 20220610
                checkData.Add(dtoCheckInfo);
            }
        }

        if (strType == "2")
        {
            foreach (DataRow reportRow in Lossdt.Rows)
            {
                ContainerCheckInfoDTO dtoCheckInfo = new ContainerCheckInfoDTO();
                dtoCheckInfo.ContainerName = row["ContainerName"].ToString();
                dtoCheckInfo.ContainerID = row["ContainerID"].ToString();
                dtoCheckInfo.WorkflowstepID = row["WorkflowStepID"].ToString();
                dtoCheckInfo.WIPQty = Convert.ToInt32(row["WipQty"].ToString());

                if (Convert.ToInt32(reportRow["Qty"]) == 0) // 试件报工为 0 情况
                {
                    dtoCheckInfo.CheckQty = dtoCheckInfo.WIPQty - Convert.ToInt32(reportRow["lossqty"]);
                }
                else
                {
                    dtoCheckInfo.CheckQty = Convert.ToInt32(reportRow["Qty"]) - Convert.ToInt32(reportRow["lossqty"]);
                }

                dtoCheckInfo.ContainerStepWorkReportID = reportRow["ContainerStepWorkReportID"].ToString();
                dtoCheckInfo.FactoryID = userInfo.FactoryID;
                dtoCheckInfo.CheckerID = userInfo.EmployeeID;
                dtoCheckInfo.CheckNote = obj["checkNote"].ToString();//检验备注
                dtoCheckInfo.FirstCheckContainerNo = obj["firstCheckContainerNo"].ToString();//首检批次号
                dtoCheckInfo.FirstCheckBillNo = obj["firstCheckBillNo"].ToString();//首件检验单号
                dtoCheckInfo.SpecimenLossQty = Convert.ToInt32(reportRow["SpecimenLossQty"]);

                int intLossQty;
                //lossQty -> editLossQty
                if (int.TryParse(Convert.ToString(reportRow["editLossQty"]), out intLossQty))
                {
                    dtoCheckInfo.LossQty = intLossQty;
                }

                dtoCheckInfo.AcceptanceQty = dtoCheckInfo.CheckQty - dtoCheckInfo.LossQty - dtoCheckInfo.SpecimenLossQty;
                dtoCheckInfo.DefectQty = Convert.ToInt32(reportRow["editDefectqty"]);
                dtoCheckInfo.ReworkQty = Convert.ToInt32(reportRow["editReworkQty"]);
                //add by longb 2023-12-21 不合格特征 IDS
                dtoCheckInfo.UnqualifiedFeatureIds = Convert.IsDBNull(reportRow["unqualifiedfeatureids"]) ? "" : reportRow["unqualifiedfeatureids"].ToString();
                //if (row["CheckTypeNote"].ToString() == "2")
                //{
                //    dtoCheckInfo.CheckTypeNote = 2; // 装配检 add:Wangjh 2017-9-18
                //}
                dtoCheckInfo.ReportType = Convert.ToInt32(reportRow["CheckType"]); // 报工类型
                dtoCheckInfo.AcceptanceQty2 = dtoCheckInfo.AcceptanceQty - dtoCheckInfo.DefectQty - dtoCheckInfo.ReworkQty; //add:Wangjh 20220610
                checkData.Add(dtoCheckInfo);
            }
        }

        if (strType == "7")
        {
            foreach (DataRow reportRow in Lossdt.Rows)
            {
                ContainerCheckInfoDTO dtoCheckInfo = new ContainerCheckInfoDTO();
                dtoCheckInfo.ContainerName = reportRow["childContainerName"].ToString();
                dtoCheckInfo.ContainerID = reportRow["ContainerID"].ToString();
                dtoCheckInfo.WorkflowstepID = row["WorkflowStepID"].ToString();
                // 报废表中没有检验数和在制数，但单件单卡这两个数都应该是 1,也就是报工数
                dtoCheckInfo.WIPQty = 1;
                dtoCheckInfo.CheckQty = 1;
                dtoCheckInfo.ContainerStepWorkReportID = reportRow["ContainerStepWorkReportID"].ToString();
                dtoCheckInfo.FactoryID = userInfo.FactoryID;
                dtoCheckInfo.CheckerID = userInfo.EmployeeID;
                dtoCheckInfo.CheckNote = obj["checkNote"].ToString();//检验备注
                dtoCheckInfo.FirstCheckContainerNo = obj["firstCheckContainerNo"].ToString();//首检批次号
                dtoCheckInfo.FirstCheckBillNo = obj["firstCheckBillNo"].ToString();//首件检验单号
                dtoCheckInfo.SpecimenLossQty = Convert.ToInt32(reportRow["SpecimenLossQty"]);
                int intLossQty;
                //lossQty -> editLossQty
                if (int.TryParse(Convert.ToString(reportRow["editLossQty"]), out intLossQty))
                {
                    dtoCheckInfo.LossQty = intLossQty;
                }
                dtoCheckInfo.AcceptanceQty = dtoCheckInfo.CheckQty - dtoCheckInfo.LossQty - dtoCheckInfo.SpecimenLossQty;
                dtoCheckInfo.DefectQty = Convert.ToInt32(reportRow["editDefectqty"]);
                dtoCheckInfo.ReworkQty = Convert.ToInt32(reportRow["editReworkQty"]);
                //add by longb 2023-12-21 不合格特征 IDS
                dtoCheckInfo.UnqualifiedFeatureIds = Convert.IsDBNull(reportRow["unqualifiedfeatureids"]) ? "" : reportRow["unqualifiedfeatureids"].ToString();
                //if (row["CheckTypeNote"].ToString() == "2")
                //{
                //    dtoCheckInfo.CheckTypeNote = 2; // 装配检 add:Wangjh 2017-9-18
                //}
                dtoCheckInfo.ReportType = Convert.ToInt32(reportRow["CheckType"]); // 报工类型
                dtoCheckInfo.AcceptanceQty2 = dtoCheckInfo.AcceptanceQty - dtoCheckInfo.DefectQty - dtoCheckInfo.ReworkQty; //add:Wangjh 20220610
                checkData.Add(dtoCheckInfo);
            }
        }

        // Modify by Yuxj20200630 取消循环查询数据库，改为一次查询，提高速度
        string StepWorkReportIDList = "";
        // 无损特殊验证
        string wusunSql = @" select 1 from  containercheckinfo cci
                    left join workflowstep ws on ws.workflowstepid='{0}'
                    left join workflowstep laws on laws.workflowid=ws.workflowid and laws.sequence=ws.sequence-1
                    where cci.containerid='{1}' and laws.workflowstepid=cci.workflowstepid and cci.checkerid='{2}' AND cci.isuse = 0 ";

        foreach (ContainerCheckInfoDTO stepCheck in checkData) // 验证是否已存在检验（此情况针对在两台终端机同时登录同时检）
        {
            StepWorkReportIDList += stepCheck.ContainerStepWorkReportID + ",";
            if (userInfo.Factory.Contains("无损"))
            {
                if (DatabaseHelper.GetSingle(string.Format(wusunSql, stepCheck.WorkflowstepID, stepCheck.ContainerID, stepCheck.CheckerID)) != null)
                {
                    strInfo = "批次" + stepCheck.ContainerName + "上一序检验人也是" + userInfo.FullName + ",此序不允许再检验";
                    return false;
                }
            }
        }

        if (StepWorkReportIDList.Length > 0)
        {
            StepWorkReportIDList = StepWorkReportIDList.Substring(0, StepWorkReportIDList.Length - 1);
            // 验证是否已存在检验记录
            DataTable dtCheck = m_CheckObj.ContainerCheckValidateList(StepWorkReportIDList, 0);
            if (dtCheck.Rows.Count > 0)
            {
                strInfo = "批次" + dtCheck.Rows[0]["ContainerName"] + "此序已有检验记录";
                return false;
            }
            // 验证是否存在无效的报工
            if (!m_CheckObj.IsVaildWorkReportForCheck(StepWorkReportIDList, 0))
            {
                strInfo = "批次工序报工已撤销，请刷新页面";
                return false;
            }
        }

        return true;
    }

    //保存工序检验、首件检验信息
    uMESProcessResult SaveCheckInfo(JObject obj)
    {
        userInfo = m_Common.GetUserInfo(obj["employeename"].ToString(), "");
        List<ContainerCheckInfoDTO> checkData = new List<ContainerCheckInfoDTO>();
        DataTable dtChildList = JsonConvert.DeserializeObject<DataTable>(obj["postData"].ToString());//报废表格数据
        DataTable wgContainerInfo = JsonConvert.DeserializeObject<DataTable>(obj["firstCheckSelectedContainerList"].ToString());//流水卡信息表格原始数据
        DataRow containerRow = wgContainerInfo.Rows[0];

        string strMessage = "";
        string strType = containerRow["containertype"].ToString();

        if (!ValidateStepCheckInfo(obj, ref checkData, dtChildList, containerRow, ref strMessage))
        {
            return new uMESProcessResult() { ReturnData = false, RowCount = "0", Code = "200", Message = strMessage };
        };

        ServerHostInfo host = new ServerHostInfo();
        string APIUserName = "", APIPassword = "";
        // 根据分厂获取域用户信息
        m_UserLoginObject.GetDomainUser(userInfo.Factory, ref APIUserName, ref APIPassword);
        host.UserName = APIUserName;
        host.Password = APIPassword;
        DataTable levelAttributes = m_Common.GetFatoryAttributes(containerRow["factoryid"].ToString());
        List<string> repairContianer = new List<string>();//储存返件报工的批次 add:Wangjh 20180413
        List<string> testContianer = new List<string>();//储存试件报工的批次 add:Wangjh 20190325
        //如果超报存在，则获取当前检验报工记录报工时间最大的报工记录ID，超报只会在此条记录产生 create by tianFW 2018年8月30日
        string Max_date_workReportID = "";
        int changevalueqty = 0;//超报数
        //只有数量批才有超报
        DataTable containerInfo_dt = GetContainerChangeQtyAndLossqtydt(dtChildList, checkData, ref changevalueqty, ref Max_date_workReportID, strType);
        List<object[]> SQLTransList = new List<object[]>();
        //检验存储数据顺序逻辑 先存数量调整记录，再存检验记录，最后修改批次数量
        foreach (ContainerCheckInfoDTO stepCheck in checkData)
        {
            CheckQtyChangeDispose(dtChildList, stepCheck, changevalueqty, Max_date_workReportID, strType);

            //生成插入检验表的sql语句
            SQLTransList.Add(m_CheckObj.FillContainerCheckInfo(stepCheck));

            //将检验对应的报工报废数据添加到报工表
            if (stepCheck.LossQty > 0)
            {
                Dictionary<string, string> para = new Dictionary<string, string>();
                para["LossQty"] = stepCheck.LossQty.ToString();
                para["ContainerStepWorkReportID"] = stepCheck.ContainerStepWorkReportID;
                SQLTransList.Add(m_WorkReportObj.FillUpdateLossQtyInfo(para));
            }

            //根据批次id，工序id，将批次待检表数据设置为无效。
            SQLTransList.Add(m_CheckObj.FillUpdateContainerCheckSuspending(stepCheck.ContainerID, stepCheck.WorkflowstepID));

            //自动报工的更新分厂和人 update:wangjh 20220824 移到此处
            SQLTransList.Add(m_CheckObj.FillUpdateContainerStepWorkReport(new Dictionary<string, object>{{"FactoryID", userInfo.FactoryID},
                                                                                                         {"WorkerID", userInfo.EmployeeID},
                                                                                                         {"ContainerStepWorkReportID", stepCheck.ContainerStepWorkReportID}}));
            if (stepCheck.ReportType == 4)//返件报工
            {
                repairContianer.Add(stepCheck.ContainerID);
            }

            if (stepCheck.ReportType == 3)
            {
                testContianer.Add(stepCheck.ContainerID);
            }
        }

        if (SQLTransList.Count > 0)
        {
            if (!DatabaseHelper.ExecuteSqlTran(SQLTransList))
            {
                return new uMESProcessResult() { ReturnData = false, RowCount = "0", Code = "200", Message = "检验失败" };
            }
        }

        if (!CheckQtyChange(containerInfo_dt, dtChildList, strType, ref strMessage))
        {
            return new uMESProcessResult() { ReturnData = true, RowCount = "0", Code = "200", Message = strMessage };
        }

        //检验结束
        string ContainerIdList = "";
        DataTable containerQtyDT = new DataTable();
        foreach (DataRow row in wgContainerInfo.Rows)
        {
            ContainerIdList += String.Format(",{0}", row["ContainerID"].ToString());
        }
        if (ContainerIdList.Length > 0)
        {
            ContainerIdList = ContainerIdList.ToString().Substring(1).Replace(",", "','");
            containerQtyDT = m_CheckObj.GetAllAcceptQtyList(ContainerIdList);
        }

        foreach (DataRow row in wgContainerInfo.Rows)
        {
            //工序检 不需要移到下一序 creat:Wangjh 2017-6-10 
            DataRow[] drs = containerQtyDT.Select(String.Format("ContainerID='{0}'", row["ContainerID"].ToString())); //一定有值?原逻辑不做改动 
            DataTable containerQty = drs.CopyToDataTable();
            int wipQty = 0;
            if (!Convert.IsDBNull(containerQty.Rows[0]["QTY"]))
            {
                wipQty = Convert.ToInt32(containerQty.Rows[0]["QTY"]);
            }
            int accepttanceQty = 0;
            if (!Convert.IsDBNull(containerQty.Rows[0]["ACCEPTANCEQTY"]))
            {
                accepttanceQty = Convert.ToInt32(containerQty.Compute("SUM(ACCEPTANCEQTY)", ""));
            }
            int lossQty = 0;
            lossQty = Convert.ToInt32(containerQty.Compute("SUM(LOSSQTY)", ""));
            if (lossQty > 0)
            {
                Dictionary<string, string> updatePara = new Dictionary<string, string>();
                Dictionary<string, string> conditionPara = new Dictionary<string, string>();
                conditionPara["ContainerID"] = string.Format("'{0}'", row["ContainerID"].ToString());
                updatePara["alllossqty"] = lossQty.ToString();
                m_ConCurrentinfo.UpdateContainerCurrentInfoByField(updatePara, conditionPara);
            }
            //检查总表stepcheckNum,firstCheckNum
            string strUpdateinfo = "";
            strUpdateinfo = m_ConCurrentinfo.UpdateContainerCurrentinfoCheckInfo(row["ContainerID"].ToString(), row["WorkflowStepID"].ToString());
            if (accepttanceQty == 0)
            {
                if (strType == "7")
                {
                    continue;
                }
                else
                {
                    break;
                }
            }

            //首检 不需要移到下一序 creat:Wangjh 2017-6-10
            if (row["FirstCheckNum"].ToString() == "1")
            {
                if (row["WipQty"].ToString() != "1")
                {
                    continue;
                }
            }
            else
            {
                //如果是返件报工则不需要干完就移到下序
                if (!testContianer.Contains(row["ContainerID"].ToString()) && !repairContianer.Contains(row["ContainerID"].ToString()) && wipQty > accepttanceQty)//合格数小于在制数没做完
                {
                    continue;
                }
            }

            //update:Wangjh 20221029 统一调用移动方法
            m_CheckObj.MoveNextStep(new Dictionary<string, string>{{"ContainerID", row["ContainerID"].ToString()},
                                                                   {"WorkflowStepID", row["WorkFlowStepID"].ToString()},
                                                                   {"WorkflowID", row["WorkflowID"].ToString()},
                                                                   {"Sequence", row["Sequence"].ToString()},
                                                                   {"ContainerName", row["ContainerName"].ToString()}}, host, accepttanceQty, levelAttributes, userInfo, ref strMessage);
        }
        return new uMESProcessResult() { ReturnData = true, RowCount = "0", Code = "200", Message = "检验成功" };
    }

    /// <summary>
    /// 获取批次超报数、报废数、超报报工ID信息 add by tianFW 2018年11月5日
    /// </summary>
    /// <param name="dtChildList">明细表</param>
    /// <param name="checkData">检验记录数组</param>
    /// <param name="changevalueqty">超报数量</param>
    /// <param name="Max_date_workReportID">最大报工时间报工</param>
    /// <param name="strtype">批次类型</param>
    /// <returns></returns>
    DataTable GetContainerChangeQtyAndLossqtydt(DataTable dtChildList, List<ContainerCheckInfoDTO> checkData, ref int changevalueqty, ref string Max_date_workReportID, string strtype)
    {
        int checkAllQty = 0; // 批次本次检验的总数量  
        int lossAllQty = 0; // 批次本次检验报废的总数量  
        int beforeCheckAppectionQty = 0; // 批次当前序在本次检验之前的检验合格数量  
        DataTable container_dt = dtChildList.DefaultView.ToTable(true, "ContainerID");
        container_dt.Columns.Add("lossQty", typeof(int)); // 本次报废数量  
        container_dt.Columns.Add("changeQty", typeof(int)); // 本次检验超报数  

        int wQty = 0; // 在制数  

        //Modify by Yuxj20206030 批量查询
        DataTable dtContainerIDList = new DataTable();
        if (strtype == "2")
        {
            string ContainerIDList = "";
            foreach (DataRow dr in container_dt.Rows)
            {
                ContainerIDList += dr["ContainerID"] + ",";
            }
            if (ContainerIDList.Length > 0)
            {
                ContainerIDList = ContainerIDList.Substring(0, ContainerIDList.Length - 1);
                dtContainerIDList = m_CheckObj.GetAllAcceptQtyList(ContainerIDList);
            }
        }

        foreach (DataRow dr in container_dt.Rows)
        {
            changevalueqty = 0;
            foreach (ContainerCheckInfoDTO stepCheck in checkData)
            {
                if (dr["ContainerID"].ToString() == stepCheck.ContainerID)
                {
                    checkAllQty += stepCheck.CheckQty;
                    if (strtype == "7")
                    {
                        lossAllQty = stepCheck.LossQty + stepCheck.SpecimenLossQty;//add:Wangjh 20181221增加需开废票试件数
                    }
                    else
                    {
                        lossAllQty = lossAllQty + stepCheck.LossQty + stepCheck.SpecimenLossQty;
                    }
                    wQty = stepCheck.WIPQty;
                }
            }
            dr["lossQty"] = lossAllQty;
            if (strtype == "2") //'只有数量批才有超报
            {
                beforeCheckAppectionQty = 0;
                if (dtContainerIDList.Rows.Count > 0)
                {
                    DataRow[] drs = dtContainerIDList.Select(String.Format("ContainerID='{0}'", dr["ContainerID"]));
                    if (drs.Length > 0)
                    {
                        beforeCheckAppectionQty += Convert.ToInt32(drs[0]["ACCEPTANCEQTY"]);
                    }
                }
                changevalueqty = checkAllQty + beforeCheckAppectionQty - wQty;
                if (changevalueqty < 0)
                {
                    changevalueqty = 0;
                }
                else if (changevalueqty > 0)
                {
                    Double max_data = -1;
                    foreach (DataRow vdr in dtChildList.Rows)
                    {
                        if (dr["ContainerID"].ToString() != vdr["ContainerID"].ToString())
                        {
                            continue;
                        }
                        DateTime currentDate = DateTime.Parse(vdr["CreateDate"].ToString()); // 将字符串转换为DateTime对象  
                        double currentOADate = currentDate.ToOADate(); // 将DateTime对象转换为OADate（双精度浮点数）  

                        if (currentOADate > max_data)
                        {
                            max_data = currentOADate; // 更新最大日期（OADate格式）  
                            Max_date_workReportID = vdr["ContainerStepWorkReportID"].ToString(); // 假设ContainerStepWorkReportID是一个整数，并将其转换为int类型  
                        }
                    }
                }
            }
            dr["changeQty"] = changevalueqty;
        }
        return container_dt;
    }

    /// <summary>
    /// 检验数量调整记录处理 add by tianFW 2018年11月5日
    /// </summary>
    /// <param name="dtChildList">明细表</param>
    /// <param name="stepCheck">检验记录</param>
    /// <param name="changevalueqty">超报数量</param>
    /// <param name="Max_date_workReportID">最大报工时间报工</param>
    /// <param name="strtype">批次类型</param>
    void CheckQtyChangeDispose(DataTable dtChildList, ContainerCheckInfoDTO stepCheck, int changevalueqty, string Max_date_workReportID, string strtype)
    {
        //如果存在超报或者报废(超报只能是数量批，检验只会存在一个批次，所以超报数是对应唯一的批次，不用再循环对比批次获取超报数)
        if (!(stepCheck.LossQty == 0 && changevalueqty == 0 && stepCheck.SpecimenLossQty == 0))
        {
            if ((stepCheck.LossQty != 0 || stepCheck.SpecimenLossQty != 0) && changevalueqty == 0)//如果存在报废但是没有超报
            {
                if (stepCheck.LossQty > 0 || stepCheck.SpecimenLossQty > 0)
                {
                    CheckQtyChangeLoss(dtChildList, stepCheck, strtype);
                }
            }
            else if ((stepCheck.LossQty != 0 || stepCheck.SpecimenLossQty != 0) && changevalueqty != 0)//如果存在报废且超报,存在超报的都是数量批
            {
                //添加批次数量改变记录--超报记录
                if (Max_date_workReportID == stepCheck.ContainerStepWorkReportID)
                {
                    CheckQtyChangeAdd(dtChildList, Max_date_workReportID, stepCheck, changevalueqty);
                }
                //添加批次数量改变记录--报废记录
                if (stepCheck.LossQty > 0 || stepCheck.SpecimenLossQty > 0)
                {
                    CheckQtyChangeLoss(dtChildList, stepCheck, strtype);
                }
            }
            else if (stepCheck.LossQty == 0 && stepCheck.SpecimenLossQty == 0 && changevalueqty != 0)//如果没有报废且超报,存在超报的都是数量批
            {
                //添加批次数量改变记录--超报记录
                if (Max_date_workReportID == stepCheck.ContainerStepWorkReportID)
                {
                    CheckQtyChangeAdd(dtChildList, Max_date_workReportID, stepCheck, changevalueqty);
                }
            }
        }
    }

    /// <summary>
    /// 增加检验记录 --报废 add by tianFW 2018年11月5日
    /// </summary>
    /// <param name="dtChildList">明细表</param>
    /// <param name="stepCheck">检验记录</param>
    /// <param name="strtype">批次类型</param>
    void CheckQtyChangeLoss(DataTable dtChildList, ContainerCheckInfoDTO stepCheck, string strtype)
    {
        string containerID = "";
        DataTable resonDt = m_CheckObj.GetLossReasonbyName("试件报废");
        foreach (DataRow dr in dtChildList.Rows)
        {
            containerID = dr["containerID"].ToString();
            if (dr["ContainerStepWorkReportID"].ToString() != stepCheck.ContainerStepWorkReportID)
            {
                continue;
            }

            //lossQty -> editLossQty
            if (!String.IsNullOrWhiteSpace(Convert.ToString(dr["editLossQty"])))
            {
                if (Convert.ToInt32(dr["editLossQty"].ToString()) > 0)
                {
                    if (strtype == "3")
                    {
                        containerID = dr["ChildContainerID"].ToString();
                    }
                    AddQtyChangRecord(stepCheck.ContainerCheckInfoID,
                                      containerID,
                                      2,
                                      -(Convert.ToInt32(dr["editLossQty"])),
                                      dr["ReasonID"].ToString(),
                                      stepCheck.ContainerStepWorkReportID,
                                      stepCheck.WorkflowstepID);
                }
            }

            if (!String.IsNullOrWhiteSpace(Convert.ToString(dr["SpecimenLossQty"])))//开废票试件数报废
            {
                if (Convert.ToInt32(dr["SpecimenLossQty"].ToString()) > 0)
                {
                    if (strtype == "3")//批量带子序号
                    {
                        containerID = dr["ChildContainerID"].ToString();
                    }
                    string resonId = "试件报废";
                    if (resonDt.Rows.Count > 0)
                    {
                        resonId = resonDt.Rows[0]["lossreasonid"].ToString();
                    }
                    AddQtyChangRecord(stepCheck.ContainerCheckInfoID, containerID, 2, -(Convert.ToInt32(dr["SpecimenLossQty"])), resonId, stepCheck.ContainerStepWorkReportID, stepCheck.WorkflowstepID);
                }
            }
        }
    }

    /// <summary>
    /// 添加批次数量改变记录 create by tianFW  2018年8月30日
    /// </summary>
    /// <param name="checkInfoID">检验记录ID</param>
    /// <param name="containerID">批次ID</param>
    /// <param name="type">添加记录类型 1 添加 2 报废</param>
    /// <param name="qty">改变数量</param>
    /// <param name="ReasonID">改变原因ID</param>
    /// <param name="ContainerStepWorkReportID">报工id</param>
    /// <param name="workflowStepID">工序ID</param>
    void AddQtyChangRecord(string checkInfoID, string containerID, int type, int qty, string ReasonID, string ContainerStepWorkReportID, string workflowStepID)
    {
        Dictionary<string, string> para = new Dictionary<string, string>();
        para["containerCheckInfoID"] = checkInfoID;
        para["containerID"] = containerID;
        para["changeQtyType"] = type.ToString();
        para["qty"] = qty.ToString();
        para["reasonID"] = ReasonID;
        para["containerStepWorkReportID"] = ContainerStepWorkReportID;
        para["scrapSourceType"] = "1";
        para["EmployeeID"] = userInfo.EmployeeID;
        para["WorkflowstepID"] = workflowStepID;
        m_ContainerObj.AddCheckQtyChangeRecord(para);
    }

    /// <summary>
    /// 增加检验记录 --超报 add by tianFW 2018年11月5日
    /// </summary>
    /// <param name="dtChildList">明细表</param>
    /// <param name="Max_date_workReportID">最大报工时间报工ID</param>
    /// <param name="stepCheck">检验记录</param>
    /// <param name="changevalueqty">超报数量</param>
    void CheckQtyChangeAdd(DataTable dtChildList, string Max_date_workReportID, ContainerCheckInfoDTO stepCheck, int changevalueqty)
    {
        DataTable qtyadjustrea_dt = m_Common.GetQtyAdjustReason();
        foreach (DataRow dr in dtChildList.Rows)
        {
            if (dr["ContainerStepWorkReportID"] == Max_date_workReportID)
            {
                string reasonID = "";
                foreach (DataRow dr_ in qtyadjustrea_dt.Rows)
                {
                    if (dr_["qtyadjustreasonname"] == "报工数量变更")
                    {
                        reasonID = dr_["qtyadjustreasonid"].ToString();
                        break;
                    }
                }
                AddQtyChangRecord(stepCheck.ContainerCheckInfoID, dr["containerID"].ToString(), 1, changevalueqty, reasonID, stepCheck.ContainerStepWorkReportID, stepCheck.WorkflowstepID);
                break;
            }
        }
    }

    /// <summary>
    /// 进行批次数量变更 add by tianFW 2018年11月5日
    /// </summary>
    /// <param name="containerInfo_dt">批次数量变化表</param>
    /// <param name="dtChildList">批次报废信息表</param>
    /// <param name="strType">批次类型</param>
    /// <param name="strMsg">返回信息</param>
    /// <returns></returns>
    bool CheckQtyChange(DataTable containerInfo_dt, DataTable dtChildList, string strType, ref string strMsg)
    {
        //只有数量批才有超报
        foreach (DataRow dr in containerInfo_dt.Rows)
        {
            if (int.Parse(dr["lossQty"].ToString()) != 0 || int.Parse(dr["changeQty"].ToString()) != 0)
            {
                if (strType == "3")
                {
                    // update:Wangjh 20220714 带子序号不走 api
                    if (!m_ContainerObj.ChangeContainerQty(dr["ContainerID"].ToString(), int.Parse(dr["changeQty"].ToString()) - int.Parse(dr["lossQty"].ToString())))
                    {
                        strMsg = "数量更新失败";
                        return false;
                    }
                    DataView dv = dtChildList.DefaultView;
                    dv.RowFilter = string.Format("editLossQty>0");//lossQty -> editLossQty
                    DataTable childdt = dv.ToTable();
                    foreach (DataRow r in childdt.Rows)
                    {
                        // 子序号批次置为关闭
                        ExcuteEntity exuteEntity = new ExcuteEntity("container", ExcuteEntity.ExcuteTypeEnum.update);
                        exuteEntity.ExcuteFileds = new List<FieldEntity> {
                            new FieldEntity("status", 2, FieldEntity.FieldTypeEnum.Numer),
                            new FieldEntity("qty", 0, FieldEntity.FieldTypeEnum.Numer)
                        };
                        exuteEntity.WhereFileds = new List<FieldEntity> {
                            new FieldEntity("Containerid", r["ChildContainerID"].ToString(), FieldEntity.FieldTypeEnum.Str)
                        };
                        DatabaseHelper.ExecuteDataByEntity(exuteEntity);
                    }
                    LogHelp.WriteOrcale("检验日志记录" + "@^" + "批次：" + dr["ContainerID"].ToString() + "@^" + "修改批次数量成功" + "@^" + Guid.NewGuid().ToString() + "@^" + userInfo.FullName);
                }
                else
                {
                    if (int.Parse(dr["changeQty"].ToString()) - int.Parse(dr["lossQty"].ToString()) != 0)
                    {
                        if (!m_ContainerObj.ChangeContainerQty(dr["ContainerID"].ToString(), int.Parse(dr["changeQty"].ToString()) - int.Parse(dr["lossQty"].ToString())))
                        {
                            strMsg = "数量更新失败";
                            return false;
                        }
                        LogHelp.WriteOrcale("检验日志记录" + "@^" + "批次：" + dr["ContainerID"].ToString() + "@^" + "修改批次数量成功" + "@^" + Guid.NewGuid().ToString() + "@^" + userInfo.FullName);
                    }
                }
            }
        }
        return true;
    }

    uMESProcessResult SaveCheckPointSession(HttpContext context, JObject obj)
    {
        DataTable dt = JsonConvert.DeserializeObject<DataTable>(obj["data"].ToString());
        var s = context.Session["PopupData"];
        if (context.Session != null)
        {
            context.Session["PopupData"] = dt;
        }
        return new uMESProcessResult() { ReturnData = dt, RowCount = "0", Code = "200", Message = "请求成功" };
    }

    //查询超越单信息
    uMESProcessResult GetSurpassBill(JObject obj)
    {
        uMESProcessResult r = new uMESProcessResult();
        DataTable selectDt = JsonConvert.DeserializeObject<DataTable>(obj["postData"].ToString());
        var para = new Dictionary<string, string>();
        para.Add("ProductName", selectDt.Rows[0]["ProductName"].ToString());
        DataTable workFlowDt = m_Common.GetWorkFlowNameByWorkFLowID(selectDt.Rows[0]["WorkFLowID"].ToString());
        para.Add("ProcessNo", workFlowDt.Rows[0]["process_No"].ToString());
        string ContainerID = string.Empty;
        foreach (DataRow row in selectDt.Rows)
        {
            ContainerID += "'" + row["ContainerID"] + "',";
        }
        if (!string.IsNullOrWhiteSpace(ContainerID))
        {
            para.Add("ContainerID", ContainerID.TrimEnd(','));
        }
        DataTable surpassDt = m_Common.QuerySurpassBillInfo(para);
        if (surpassDt.Rows.Count == 0)
        {
            r = new uMESProcessResult() { ReturnData = null, RowCount = "0", Code = "300", Message = "所选批次无超越单" };
        }
        else
        {
            DataTable tempDt = surpassDt.DefaultView.ToTable(true, "surpassbillinfoid");
            string surpassbillinfoid = string.Empty;
            foreach (DataRow row in tempDt.Rows)
            {
                surpassbillinfoid += row["surpassbillinfoid"] + ",";
            }
            DataTable surpassAccessories = m_Common.GetSurpassAccessories(surpassbillinfoid.TrimEnd(','));
            var data = new Dictionary<string, object>();
            data.Add("list", surpassDt);
            data.Add("acces", surpassAccessories);
            r = new uMESProcessResult() { ReturnData = data, RowCount = "0", Code = "200", Message = "" };
        }
        return r;
    }

    // 检验前校验是否存在未录入实测值
    uMESProcessResult isInputCheckPointResult(JObject obj)
    {
        DataTable dt = JsonConvert.DeserializeObject<DataTable>(obj["postData"].ToString());
        bool hasCheckPoint = m_CheckObj.IsInputCheckPointResult(dt);
        return new uMESProcessResult() { ReturnData = hasCheckPoint, RowCount = "0", Code = "200", Message = "请求成功" };
    }

    //保存理化或计量标识
    uMESProcessResult saveCheckEntrust(JObject obj)
    {
        DataTable postData = JsonConvert.DeserializeObject<DataTable>(obj["postData"].ToString());
        foreach (DataRow dr in postData.Rows)
        {
            string sql = @"SELECT t.containersteprecordid,t.containername,t.workflowstepname,t.entrustmeasurement 
                           FROM r_checkcycleboard t
                           WHERE t.workflowstepname = '{0}' AND t.containername = '{1}'";
            sql = string.Format(sql, dr["workflowstepname"].ToString(), dr["containername"].ToString());
            DataTable dt = DatabaseHelper.Query_ReturnDatTableBy77(sql);

            if (dt.Rows.Count > 0)
            {
                //检验周期中间表有数据，直接更新字段
                string updateSql = string.Format("UPDATE r_checkcycleboard t SET t.entrustmeasurement = '1' WHERE t.workflowstepname = '{0}' AND t.containername = '{1}'",
                    dr["workflowstepname"].ToString(),
                    dr["containername"].ToString());
                DatabaseHelper.ExecuteSqlBy77(updateSql);
            }
            else
            {
                string checkcycleboardSql = @"SELECT csr.containername,csr.workflowstepname,fa.factoryid,fa.factoryname,f.factorycode,
                   cci.fromworkcentername,cci.mfgordername,cci.familylistnames,cci.productname,cci.productdescription productdesc,
                   csr.reportdate,csr.reportemployeename reporter,csr.checkdate,csr.checkemployeename checker,cu.notes checksuspendnotes,
            csr.lossqty,csr.passqty+NVL(csr.defectqty,0)+NVL(csr.reworkqty,0) passqty,csr.containersteprecordid,
                   s.lastcheck,s.factoryid specfactoryid,'' status,'' specchecktype,csr.containerid,csr.workflowstepid
            FROM (
                SELECT csr.* 
                FROM containersteprecord csr 
                WHERE NVL2(csr.containersteprecordid,'1','0')='1' AND csr.workflowstepname = '{0}' AND csr.containername = '{1}' 
            ) csr
            INNER JOIN containercurrentinfo cci ON cci.containerid=csr.containerid
            LEFT JOIN factory fa ON fa.factoryid=cci.originalfactoryid--主制车间
            LEFT JOIN mes_factory_mapping f ON f.factoryid = fa.factoryid
            LEFT JOIN containerchecksuspending cu ON cu.containerid=csr.containerid AND cu.workflowstepid=csr.workflowstepid AND cu.isuse=0--待处理
            LEFT JOIN spec s ON s.specid=csr.specid
            LEFT JOIN r_checkcycleboard@mesreport rc ON rc.containersteprecordid=csr.containersteprecordid
            WHERE NVL2(rc.containersteprecordid,'1','0')='0'";
                checkcycleboardSql = string.Format(checkcycleboardSql, dr["workflowstepname"].ToString(), dr["containername"].ToString());
                DataTable insertDt = DatabaseHelper.Query_ReturnDatTable(checkcycleboardSql);
                if (insertDt.Rows.Count > 0)
                {
                    string insertSql = @"
INSERT INTO r_checkcycleboard rc
(rc.factoryname,rc.factorycode,rc.containername,rc.workflowstepname,rc.fromworkcentername,rc.mfgordername,
rc.familylistnames,rc.productname,rc.productdesc,
rc.checker,rc.checksuspendnotes,rc.REPORTER,rc.reportdate,rc.checkdate,rc.status,rc.lossqty,rc.passqty,
rc.containersteprecordid,
rc.specchecktype,rc.containerid,rc.workflowstepid,entrustmeasurement) 
VALUES ('{0}','{1}','{2}','{3}','{4}','{5}','{6}','{7}','{8}','{9}','{10}','{11}',
to_date('{12}','yyyy/mm/dd hh24:mi:ss'),to_date('{13}','yyyy/mm/dd hh24:mi:ss'),'{14}','{15}','{16}','{17}','{18}','{19}','{20}','{21}')";

                    DataRow row = insertDt.Rows[0];
                    if (row["lastcheck"].ToString() == "1")
                    {
                        if (row["specfactoryid"].ToString() == row["factoryid"].ToString())
                        {
                            row["specchecktype"] = "2"; //检验工序（不包括转工序）
                        }
                        else
                        {
                            row["specchecktype"] = "3"; //转工检验工序（既是检验序又是转工序）
                        }
                    }
                    else
                    {
                        if (row["specfactoryid"].ToString() == row["factoryid"].ToString())
                        {
                            row["specchecktype"] = "1"; //普通工序
                        }
                        else
                        {
                            row["specchecktype"] = "4"; //转工序（不包括检序）
                        }
                    }

                    insertSql = string.Format(insertSql,
                        row["factoryname"].ToString(),
                        row["factorycode"].ToString(),
                        row["containername"].ToString(),
                        row["workflowstepname"].ToString(),
                        row["fromworkcentername"].ToString(),
                        row["mfgordername"].ToString(),
                        row["familylistnames"].ToString(),
                        row["productname"].ToString(),
                        row["productdesc"].ToString(),
                        row["checker"].ToString(),
                        row["checksuspendnotes"].ToString(),
                        row["REPORTER"].ToString(),
                        row["reportdate"].ToString(),
                        row["checkdate"].ToString(), "1",
                        row["lossqty"].ToString(),
                        row["passqty"].ToString(),
                        row["containersteprecordid"].ToString(),
                        row["specchecktype"].ToString(),
                        row["containerid"].ToString(),
                        row["workflowstepid"].ToString(), "1");
                    DatabaseHelper.ExecuteSqlBy77(insertSql);
                }
            }
        }
        return new uMESProcessResult() { ReturnData = true, RowCount = "0", Code = "200", Message = "请求成功" };
    }
}